#include "Common.hpp"
#include "User.hpp"
#include "ThreadPool.hpp"
using namespace MyThreadPoolMudule;
#include <cstring>
#include <sys/wait.h>

class udp_server
{
public:
    struct ptheadData{
        udp_server* self;
        int fd;
    };
    using task_t = std::function<void()>;
    using func_t = std::function<string(string& cmdstr)>;
    udp_server(uint16_t port = 8080)
        :_port(port)
    {

    }
    void Init(){
        _listensocketfd = socket(AF_INET,SOCK_STREAM,0);
        if (_listensocketfd < 0){
            LOG(ERROR) << "socket create error";
            exit(-1);
        }
        uint16_t port = ::htons(_port);
        //bind操作
        InetAddr local(port);
        if(::bind(_listensocketfd,local.Addr(),local.Len()) < 0){
            LOG(ERROR) << "bind error";
            exit(-1);
        }
        if (::listen(_listensocketfd,BACKLOG) < 0){
            LOG(ERROR) << "listen error";
            exit(-1);
        }
    }
    void Register(func_t f){
        _func = f;
    }
    void HandlerRequest(int fd){
        LOG(INFO) << "HandlerRequest fd is" << fd;
        char buffer[1024];
        while(1){
            ssize_t n = ::read(fd,buffer,sizeof(buffer));
            if (n > 0){
                buffer[n] = 0;
                LOG(INFO) << "client: " << buffer;
                string tmp = buffer;
                string message = _func(tmp);
                ::write(fd,message.c_str(),message.size());
            }
            else if(n == 0){
                LOG(INFO) << "client quit";
                break;
            }
            else return;
        }
        //关闭文件描述符
        ::close(fd);
    }
    static void* routine(void* args){
       ptheadData* data = static_cast<ptheadData*>(args);
       data->self->HandlerRequest(data->fd);
       delete data;
       return nullptr;
    }
    void Start(){
        LOG(INFO) << "开始执行";
        while(true){
            sockaddr_in peer;
            socklen_t Len = sizeof(peer);
            // LOG(DEBUG) << "listenfd: " << _listensocketfd;
            // LOG(DEBUG) << "我的进程id: " << getpid();
            int  fd = ::accept(_listensocketfd,CONV(&peer),&Len);
            if (fd < 0){
                LOG(ERROR) << "accept error";
                // LOG(ERROR) << strerror(errno);
                break;
            }
            LOG(INFO) << "accept success, fd is : " << fd;
            //version3  线程池
            // ThreadPool<task_t>::GetInstance()->Enque([this,fd](){
            //     this->HandlerRequest(fd);
            // });
            // version2 原生线程库
            ptheadData* data = new ptheadData();
            data->self = this;
            data->fd = fd;
            pthread_t pid;
            pthread_create(&pid,nullptr,routine,(void*)data);
            pthread_detach(pid);
            //version1 多线程
            // pid_t pid = fork();
            // if (pid == 0){
            //     //关闭没有必要的买哦舒服
            //     ::close(_listensocketfd);
            //     if (fork() > 0) exit(0);
            //     //孙子进程, 孤儿进程, 资源有系统来释放
            //     // LOG(DEBUG) << "我的进程id: " << getpid();
            //     HandlerRequest(fd);
            //     exit(0);
            // }
            // //父进程关闭不需要的文件描述符
            // ::close(fd); //要关闭, 不然就是文件描述符泄漏了.
            // if (waitpid(pid,nullptr,0) < 0){
            //     LOG(ERROR) << "wait error";
            // }
        }
    }
    ~udp_server(){
        ::close(_listensocketfd);
    }
private:
    int _listensocketfd;
    uint16_t _port;
    func_t _func;
};
